package com.manage.gateway.config;

import cn.hutool.core.util.ArrayUtil;
import com.manage.common.core.constants.Constant;
import com.manage.gateway.auth.TokenAuthManager;
import com.manage.gateway.component.AuthAccessDeniedHandler;
import com.manage.gateway.component.TokenAuthenticationEntryPoint;
import com.manage.gateway.filter.WhiteListRemoveJwtFilter;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter;
import org.springframework.security.web.server.SecurityWebFilterChain;
import reactor.core.publisher.Mono;

import java.util.Arrays;

/**
 * 资源服务器配置
 * @author zq
 */
@AllArgsConstructor
@Configuration
@EnableWebFluxSecurity
public class ResourceServerConfig {
    private final TokenAuthManager tokenAuthManager;
    private final ApplicationProperties properties;
    private final AuthAccessDeniedHandler authAccessDeniedHandler;
    private final TokenAuthenticationEntryPoint tokenAuthenticationEntryPoint;
    private final WhiteListRemoveJwtFilter whiteListRemoveJwtFilter;

    @Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {

        http.oauth2ResourceServer().jwt()
                .jwtAuthenticationConverter(jwtAuthenticationConverter());
//        http.oauth2ResourceServer().opaqueToken().introspectionUri(properties.getAuth().getCheckToken())
//                .introspectionClientCredentials(Constant.RESOURCE_CLIENT_ID,Constant.RESOURCE_CLIENT_SECRET);
        //自定义处理验证错误的结果
        http.oauth2ResourceServer().authenticationEntryPoint(tokenAuthenticationEntryPoint);
        //对白名单路径，直接移除JWT请求头
        http.addFilterBefore(whiteListRemoveJwtFilter,SecurityWebFiltersOrder.AUTHENTICATION);
        http.authorizeExchange()
                .pathMatchers(ArrayUtil.toArray(Arrays.asList(properties.getExclude().getTokenFilterExclude()),String.class)).permitAll()
                .anyExchange().access(tokenAuthManager)
                .and().exceptionHandling()
                .accessDeniedHandler(authAccessDeniedHandler)
                .authenticationEntryPoint(tokenAuthenticationEntryPoint)
                .and().csrf().disable();
        return http.build();
    }

    @Bean
    public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() {
        JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
        jwtGrantedAuthoritiesConverter.setAuthorityPrefix(Constant.AUTHORITY_PREFIX);
        jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(Constant.AUTHORITY_CLAIM_NAME);
        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
        return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter);
    }

}
